home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 25 / develop Issue 25 code / ToolFrontEnd / ToolFrontEnd Source / ToolFrontEnd Compiler / MySignatureToApp.c next >
Encoding:
Text File  |  1996-02-15  |  9.6 KB  |  351 lines  |  [TEXT/KAHL]

  1. ////
  2. ////    SignatureToApp.c        Implementation of the SignatureToApp function.
  3. ////
  4. ////    By Jens Alfke            ©1991 Apple Computer, Inc. All rights reserved.
  5. ////
  6. ////    Modified by Tim Maroney for ProjectDrag to not search on network volumes,
  7. ////        and (without success) to make sure that LaunchApplication actually worked.
  8. ////
  9.  
  10. #include <Errors.h>
  11. #include <Files.h>
  12. #include <Processes.h>
  13. #include <Folders.h>
  14. #include <AppleEvents.h>
  15.  
  16. #include "SignatureToApp.h"
  17.  
  18.  
  19.    ////////////////////////////////////////////////////////////
  20.   //    FindRunningAppBySignature                            //
  21.  //            Search process list for app with this signature//
  22. ////////////////////////////////////////////////////////////
  23. static OSErr
  24. FindRunningAppBySignature( OSType sig, ProcessSerialNumber *psn, FSSpec *fileSpec )
  25. {
  26.     OSErr err;
  27.     ProcessInfoRec info;
  28.     
  29.     psn->highLongOfPSN = 0;
  30.     psn->lowLongOfPSN  = kNoProcess;
  31.     do{
  32.         err= GetNextProcess(psn);
  33.         if( !err ) {
  34.             info.processInfoLength = sizeof(info);
  35.             info.processName = NULL;
  36.             info.processAppSpec = fileSpec;
  37.             err= GetProcessInformation(psn,&info);
  38.         }
  39.     } while( !err && info.processSignature != sig );
  40.  
  41.     if( err )
  42.         fileSpec->name[0] = 0;                                // Clear name if not found
  43.     else
  44.         *psn = info.processNumber;
  45.     return err;
  46. }
  47.  
  48.  
  49.    ////////////////////////////////////////////////////////////
  50.   //    GetSysVolume                                        //
  51.  //            Get the vRefNum of the system (boot) volume       //
  52. ////////////////////////////////////////////////////////////
  53. static OSErr
  54. GetSysVolume( short *vRefNum )
  55. {
  56.     long dir;
  57.     
  58.     return FindFolder(kOnSystemDisk,kSystemFolderType,false, vRefNum,&dir);
  59. }
  60.  
  61.  
  62.    ////////////////////////////////////////////////////////////
  63.   //    GetIndVolume                                        //
  64.  //            Get the vRefNum of an indexed on-line volume   //
  65. ////////////////////////////////////////////////////////////
  66. static OSErr
  67. GetIndVolume( short index, short *vRefNum )
  68. {
  69.     ParamBlockRec pb;
  70.     OSErr err;
  71.     
  72.     pb.volumeParam.ioCompletion = NULL;
  73.     pb.volumeParam.ioNamePtr = NULL;
  74.     pb.volumeParam.ioVolIndex = index;
  75.     
  76.     err= PBGetVInfoSync(&pb);
  77.     
  78.     *vRefNum = pb.volumeParam.ioVRefNum;
  79.     return err;
  80. }
  81.  
  82.  
  83.    ////////////////////////////////////////////////////////////
  84.   //    VolHasDesktopDB                                        //
  85.  //            Check if a volume supports desktop DB calls       //
  86. ////////////////////////////////////////////////////////////
  87. static OSErr
  88. VolHasDesktopDB( short vRefNum, Boolean *hasDesktop )
  89. {
  90.     typedef struct {                        // Volume Info Rec; see IM-VI 25-32
  91.         short    vMVersion;
  92.         long    vMAttrib;
  93.         Handle    vMLocalHand;
  94.         long    vMServerAddr;
  95.         long    vMVolumeGrade;
  96.         short    vMForeignPrivID;
  97.     } VolInfoRec;
  98.     const bHasNewDesk = 1L <<12;            // Flag mask for vMAttrib field
  99.     
  100.     HParamBlockRec pb;
  101.     VolInfoRec info;
  102.     OSErr err;
  103.     
  104.     long i, *ip;
  105.     for( i=0, ip=(long*)&pb; i<sizeof(pb)/sizeof(long); i++ )        // Clear pb
  106.         *ip++ = 0;
  107.     pb.ioParam.ioCompletion = NULL;
  108.     pb.ioParam.ioNamePtr = NULL;
  109.     pb.ioParam.ioVRefNum = vRefNum;
  110.     pb.ioParam.ioBuffer = (Ptr)&info;
  111.     pb.ioParam.ioReqCount = sizeof(VolInfoRec);
  112.     
  113.     err= PBHGetVolParmsSync(&pb);            // Get volume info
  114.  
  115.     *hasDesktop = err==noErr && (info.vMAttrib & bHasNewDesk)!=0;
  116.     return err;
  117. }
  118.  
  119.  
  120.    ////////////////////////////////////////////////////////////
  121.   //    FindAppOnVolume                                        //
  122.  //            Ask vol's desktop db for application           //
  123. ////////////////////////////////////////////////////////////
  124. static OSErr
  125. FindAppOnVolume( OSType sig, short vRefNum, FSSpec *file )
  126. {
  127.     DTPBRec pb;
  128.     OSErr err;
  129.     short refNum;
  130.     
  131.     long i, *ip;
  132.     for( i=0, ip=(long*)&pb; i<sizeof(pb)/sizeof(long); i++ )        // Clear pb
  133.         *ip++ = 0;
  134.  
  135.     pb.ioCompletion = NULL;
  136.     pb.ioVRefNum = vRefNum;
  137.     pb.ioNamePtr = NULL;
  138.     err= PBDTGetPath(&pb);                // Puts DT refnum into pb.ioDTRefNum
  139.     if( err ) return err;
  140.     refNum = pb.ioDTRefNum;
  141.     
  142.     pb.ioCompletion = NULL;
  143.     pb.ioDTRefNum = refNum;
  144.     pb.ioIndex = 0;
  145.     pb.ioFileCreator = sig;
  146.     pb.ioNamePtr = (StringPtr)&file->name;
  147.     err= PBDTGetAPPLSync(&pb);                        // Find it!
  148.     
  149.     if( err == fnfErr )
  150.         err = afpItemNotFound;                        // Bug in PBDTGetAPPL
  151.     if( err )
  152.         return err;                                    // Returns afpItemNotFound if app wasn't found.
  153.  
  154.     file->vRefNum = vRefNum;
  155.     file->parID = pb.ioAPPLParID;
  156.     return noErr;
  157. }
  158.  
  159.  
  160.    ////////////////////////////////////////////////////////////
  161.   //    BuildODoc                                            //
  162.  //            Construct an 'odoc' Apple event                   //
  163. ////////////////////////////////////////////////////////////
  164. static OSErr
  165. BuildODoc( const FSSpec *fileSpec, OSType signature, const ProcessSerialNumber *psn,
  166.            AppleEvent *event )
  167. {
  168.     // If psn is non-NULL the event will be addressed to that process;
  169.     // otherwise it'll be addressed to the supplied signature.
  170.     
  171.     AEDesc addr,ev;
  172.     OSErr err;
  173.     
  174.     event->descriptorType = 0;
  175.     event->dataHandle = NULL;
  176.     
  177.     if( psn )
  178.         err= AECreateDesc(typeProcessSerialNumber,(void*)psn,sizeof(*psn), &addr);
  179.     else
  180.         err= AECreateDesc(typeApplSignature,(void*)&signature,sizeof(signature), &addr);
  181.     if( err ) return err;
  182.     
  183.     err= AECreateAppleEvent(kCoreEventClass,kAEOpenDocuments, &addr,kAutoGenerateReturnID,0,&ev);
  184.     AEDisposeDesc(&addr);
  185.     if( !err )
  186.         err= AEPutParamPtr(&ev,keyDirectObject, typeFSS,(void*)fileSpec,sizeof(FSSpec));
  187.     
  188.     if( err )
  189.         AEDisposeDesc(&ev);
  190.     else
  191.         *event = ev;
  192.     return err;
  193. }
  194.  
  195.  
  196.    ////////////////////////////////////////////////////////////
  197.   //    LaunchIt                                            //
  198.  //            Launch app once we have a location               //
  199. ////////////////////////////////////////////////////////////
  200. static OSErr
  201. LaunchIt( const FSSpec *fileSpec, LaunchFlags launchControlFlags, const AppleEvent *odoc,
  202.             ProcessSerialNumber *psn )
  203. {
  204.     LaunchParamBlockRec pb;
  205.     AEDesc paramDesc;
  206.     OSErr err;
  207.     
  208.     pb.launchBlockID = extendedBlock;
  209.     pb.launchEPBLength = extendedBlockLen;
  210.     pb.launchFileFlags = launchNoFileFlags;
  211.     pb.launchControlFlags = launchControlFlags | launchNoFileFlags;
  212.     pb.launchAppSpec = (FSSpec*)fileSpec;
  213.     pb.launchProcessSN.highLongOfPSN = 0;
  214.     pb.launchProcessSN.lowLongOfPSN = 0;
  215.     
  216.     if( odoc ) {
  217.         err= AECoerceDesc(odoc,typeAppParameters, ¶mDesc);
  218.         if( err ) return err;
  219.         HLock(paramDesc.dataHandle);
  220.         pb.launchAppParameters = (void*) *paramDesc.dataHandle;
  221.     } else
  222.         pb.launchAppParameters = NULL;
  223.     
  224.     err= LaunchApplication(&pb);
  225.     
  226.     if( odoc )
  227.         AEDisposeDesc(¶mDesc);
  228.         
  229.     if( err == noErr ) {
  230. #if 0
  231.         // another change by Tim. LaunchApplication sometimes doesn't report
  232.         // an error even though it failed to launch. so check the PSN!
  233.         // this code did not work for some unknown reason.
  234.         ProcessInfoRec info;
  235.         EventRecord event;
  236.         
  237.         WaitNextEvent(0, &event, 0, NULL); // it doesn't launch until this call is made
  238.         info.processInfoLength = sizeof(ProcessInfoRec);
  239.         info.processName = NULL;
  240.         info.processAppSpec = NULL;
  241.         err = GetProcessInformation(&pb.launchProcessSN, &info);
  242.         if (err == noErr)
  243. #endif
  244.             *psn = pb.launchProcessSN;
  245.     }
  246.     return err;
  247. }
  248.  
  249.  
  250.    ////////////////////////////////////////////////////////////
  251.   //    SignatureToApp                                        //
  252.  //            Main routine. Find app, launching if need be   //
  253. ////////////////////////////////////////////////////////////
  254. OSErr
  255. SignatureToApp( OSType sig, const FSSpec *document,
  256.                 ProcessSerialNumber *psn, FSSpec *fileSpec, Boolean *launched,
  257.                 Sig2App_Mode mode,
  258.                 LaunchFlags launchControlFlags )
  259. {
  260.     ProcessSerialNumber dummyPSN;
  261.     OSErr err;
  262.     short sysVRefNum, vRefNum, index;
  263.     FSSpec file;
  264.     Boolean hasDesktopDB;
  265.     
  266.     if( launched )
  267.         *launched = false;
  268.     if( psn == NULL )
  269.         psn = &dummyPSN;                                // Allow psn parameter to be NIL
  270.     
  271.     // First see if it's already running:
  272.     
  273.     err= FindRunningAppBySignature(sig,psn,fileSpec);
  274.     
  275.     if( err==noErr && mode==Sig2App_LaunchApplication ) {
  276.         if( (launchControlFlags & launchDontSwitch) == 0 ) {
  277.             err= SetFrontProcess(psn);                // They wanted to switch to it…
  278.             if( err ) return err;
  279.         }
  280.         if( document ) {
  281.             // They wanna open a document, so do it:
  282.             AppleEvent aevt;
  283.             err= BuildODoc(document,sig,psn, &aevt);
  284.             if( !err )
  285.                 err= AESend(&aevt,NULL,kAENoReply | kAEAlwaysInteract,
  286.                             kAENormalPriority,kAEDefaultTimeout,
  287.                             NULL,NULL);
  288.             AEDisposeDesc(&aevt);
  289.         }
  290.         return err;
  291.     }
  292.  
  293.     if( err != procNotFound || mode<=Sig2App_FindProcess )
  294.         return err;
  295.     
  296.     // Well, it's not running but it's okay to launch it. Let's have a look around:
  297.     
  298.     err= GetSysVolume(&sysVRefNum);
  299.     if( err != noErr ) return err;    // Find boot volume
  300.     vRefNum = sysVRefNum;                                // Start search with boot volume
  301.     index = 0;
  302.     do{
  303.         if( index==0 || vRefNum != sysVRefNum ) {
  304.  
  305.             // Here's Tim's change: don't search on network volumes.
  306.             HParamBlockRec pb;
  307.             GetVolParmsInfoBuffer info;
  308.             
  309.             pb.ioParam.ioVRefNum = vRefNum;
  310.             pb.ioParam.ioNamePtr = nil;
  311.             pb.ioParam.ioBuffer = (Ptr)&info;
  312.             pb.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  313.             err = PBHGetVolParmsSync(&pb);            // Get volume info
  314.             if (err == noErr && info.vMServerAdr == 0) {
  315.         
  316.                 err= VolHasDesktopDB(vRefNum,&hasDesktopDB);
  317.                 if( err != noErr )
  318.                     return err;
  319.                 if( hasDesktopDB ) {                        // If volume has a desktop DB,
  320.                     err= FindAppOnVolume(sig,vRefNum, &file);        // ask it to find app
  321.                     if( err==noErr ) {
  322.                         // FOUND IT!
  323.                         if( fileSpec )
  324.                             *fileSpec = file;
  325.                         if( mode==Sig2App_LaunchApplication ) {
  326.                             AEDesc odoc;
  327.                             if( document )
  328.                                 err= BuildODoc(document,sig,NULL,&odoc);
  329.                             if( err ) return err;
  330.                             err= LaunchIt(&file,launchControlFlags,        // Launch it!
  331.                                             document ?&odoc :NULL,
  332.                                             psn);
  333.                             if( document )
  334.                                 AEDisposeDesc(&odoc);
  335.                             if( !err && launched )
  336.                                 *launched = true;
  337.                         }
  338.                         return err;
  339.                         
  340.                     } else if( err != afpItemNotFound )
  341.                         return err;
  342.                 }
  343.             }
  344.         }
  345.         err= GetIndVolume(++index,&vRefNum);                // Else go to next volume
  346.     } while( err==noErr );                                // Keep going until we run out of vols
  347.     
  348.     if( err==nsvErr || err==afpItemNotFound )
  349.         err= fnfErr;                                    // File not found on any volume
  350.     return err;
  351. }